﻿using System;
using System.Text;
using System.Collections;
using FluorineFx;

namespace Htxw.AMFRemoting
{
    /// <summary>
    /// RemoteMethodObject 是远程调用的最小单位，是一个远程调用的方法“元”
    /// 如果同时有多个调用，该类要构造多个。
    /// 该类包含以下三个部分组成的Object：
    ///        domain    // 命名空间
    ///        foo       // 方法名
    ///        params    // 参数对象列表（Array），每个元素为一个参数
    /// 格式：
    /// {
    ///     domain: 命名空间,
    ///     foo: 方法名,
    ///     params: 参数列表
    /// }
    /// </summary>
    public class RemoteMethodObject
    {

        /// <summary>
        /// 远程调用的“元”对像，包含domain、foo、params 元素
        /// 格式：
        /// {
        ///     domain: 命名空间,
        ///     foo: 方法名,
        ///     params: 参数列表
        /// }
        /// </summary>
        private readonly ASObject _methodObject = new ASObject();
        /// <summary>
        /// params  参数列表对象，每个元素为一个参数
        /// 格式：
        /// [
        ///     param1, param2 ...
        /// ]
        /// </summary>
        private ArrayList _paramsArray = new ArrayList();


        /// <summary>
        /// 是否已添加元素到 params 列表中，调用了 SetParams() 则为真
        /// 注：如果isSetParam 为真，则 SetParamsNull()、AddParams()、SetParams() 均失效
        /// </summary>
        private bool _isSetParam;


        /// <summary>
        /// 构造函数: 初始化该类内部的对象，远程调用的Domain\Foo\params
        /// </summary>
        /// <param name="foo">Foo</param>
        public RemoteMethodObject(string foo)
        {

            _methodObject.Add("domain", HtConfig.ServerDomain);
            _methodObject.Add("foo", foo);
        }
        /// <summary>
        /// 构造函数: 初始化该类内部的对象，远程调用的Domain\Foo\params
        /// </summary>
        /// <param name="foo">Foo</param>
        /// <param name="domain">domain</param>
        public RemoteMethodObject(string foo, string domain)
        {
            _methodObject.Add("domain", domain);
            _methodObject.Add("foo", foo);
        }

        /// <summary>
        /// 给RemoteMethodObject 的Params加一个参数
        /// </summary>
        /// <param name="value">参数值</param>
        /// <returns>void</returns>
        public void AddParams(object value)
        {
            if (!_isSetParam)
            {
                _paramsArray.Add(value);
            }
        }


        /// <summary>
        ///  设置params为空，使用无参数的远程调用接口时调用
        /// </summary>
        /// <returns>void</returns>
        public void SetParamsNull()
        {
            if (!_isSetParam)
            {
                _paramsArray = new ArrayList();
            }
        }


        /// <summary>
        ///  设置params为外部ArrayList对像, 
        /// </summary>
        /// <param name="a">参数列表</param>
        /// <returns>void</returns>
        public void SetParams(Array a)
        {
            if (_isSetParam) return;
            _isSetParam = true;
            _methodObject.Add("params", a);
        }
        
        /// <summary>
        /// 获得RemoteMethodObject构造的ASObject对像
        /// </summary>
        /// <returns>返回数据的格式 { domain: 命名空间, foo: 方法名, params: 参数列表 }</returns>
        public ASObject GetRemoteMethodObject()
        {
            if (!_isSetParam)
            {//非设置了外部的Param，则把内部的ParamsArray加入到MethodObject中
                _methodObject.Add("params", _paramsArray.ToArray());
            }

            if (_methodObject.Count == 0)
            {
                throw new Exception("Call to the DS Remote Method Object is Null");
            }
            if (_methodObject.Count <= 2)
            {
                throw new Exception("Call to the DS Remote Method Params is Null");
            }

            return _methodObject;
        }

        /// <summary>
        /// debug输出AMF数组
        /// </summary>
        /// <param name="o">数组对像</param>
        /// <returns>string</returns>
        public string DebugAMFArrayToTable(object[] o)
        {
            var s = new StringBuilder();
            s.AppendLine("<table border=\"1\" cellspacing=\"1\" cellpadding=\"1\">");
            for (var i = 0; i < o.Length; i++)
            {
                s.AppendLine("  <tr>");
                var oooo = o.GetValue(i);
                s.Append("    <td colspan=\"2\">数组");
                s.AppendLine("[" + i + "]</td>");
                s.AppendLine("  </tr>");
                var ooooo = (ASObject)oooo;
                IDictionaryEnumerator en = ooooo.GetEnumerator();

                while (en.MoveNext())
                {
                    s.AppendLine("  <tr>");
                    s.Append("    <td>" + en.Key + "</td>");
                    s.AppendLine("<td>" + en.Value + "</td>");
                    s.AppendLine("  </tr>");
                }
            }
            s.AppendLine("</table>");
            return s.ToString();
        }
    }
}
